home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / Open Transport 1.3 / Open Transport SDK / Open Tpt Module Developer / Samples / DLPI Template / StreamLog / StreamLogApp.cp < prev    next >
Encoding:
Text File  |  1998-04-30  |  13.7 KB  |  562 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        StreamLogApp.cp
  3.  
  4.     Contains:    Stream logging application
  5.     
  6.  
  7.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  8.  
  9. */
  10.  
  11. #include "StreamLogApp.h"
  12. #include "Time.h"
  13. #include "CTextDoc.h"
  14. #include "CDirtyText.h"
  15. #include <PP_Messages.h>
  16.  
  17. #include <LApplication.h>
  18. #include <LGrowZone.h>
  19. #include <LWindow.h>
  20. #include <LScroller.h>
  21. #include <LPrintout.h>
  22. #include <LPlaceHolder.h>
  23.  
  24. #include <UMemoryMgr.h>
  25. #include <UDrawingState.h>
  26. #include <UPowerTools.h>
  27. #include <URegistrar.h>
  28. #include <UDesktop.h>
  29. #include <SegLoad.h>
  30.  
  31. #include <StandardFile.h>
  32.  
  33. #include <Types.h>
  34.  
  35. // ===========================================================================
  36. //        • Main Program
  37. // ===========================================================================
  38.  
  39. void main(void)
  40. {
  41.                                     // Set Debugging options
  42. #ifdef Debug_Throw
  43.     gDebugThrow = debugAction_Alert;
  44. #endif
  45.  
  46. #ifdef Debug_Signal
  47.     gDebugSignal = debugAction_Alert;
  48. #endif
  49.  
  50.     InitializeHeap(3);                // Initialize Memory Manager
  51.                                     // Parameter is number of Master Pointer
  52.                                     //   blocks to allocate
  53.     
  54.                                     // Initialize standard Toolbox managers
  55.     UQDGlobals::InitializeToolbox(&qd);
  56.     
  57. #ifdef Debug_Signal                    // Check for missing MBAR, which
  58.     CheckForInitialMBAR();            // probably means that there is no
  59. #endif                                // project resource file
  60.     
  61.     
  62.     new LGrowZone(20000);            // Install a GrowZone function to catch
  63.                                     //    low memory situations.
  64.                                     //    Parameter is size of reserve memory
  65.                                     //    block to allocated. The first time
  66.                                     //    the GrowZone function is called,
  67.                                     //    there will be at least this much
  68.                                     //    memory left (so you'll have enough
  69.                                     //    memory to alert the user or finish
  70.                                     //    what you are doing).
  71.     
  72.     StreamLogApp    theApp;                // Create instance of your Application
  73.     theApp.Run();                    //   class and run it
  74. }
  75.  
  76.  
  77. char* LongToString(char* numStr, unsigned long val, Boolean doSign)
  78. {
  79.     char tempStr[16];
  80.     int ix, digit, len;
  81.     if ( doSign && ((long)val) < 0 )
  82.     {
  83.         val = (unsigned long)(-(long)val);
  84.         OTStrCopy(tempStr, "-");
  85.     }
  86.     else
  87.         OTStrCopy(tempStr, " ");
  88.     ix = 1;
  89.     do
  90.     {
  91.         digit = (int)(val % 10);
  92.         val /= 10;
  93.         tempStr[ix++] = digit | 0x30;
  94.     } while (val != 0);
  95.     len = ix;
  96.     *numStr = *tempStr;
  97.     for (ix = 1; ix < len; ix++)
  98.         numStr[len - ix] = tempStr[ix];
  99.     numStr[len] = '\0';
  100.     return numStr;
  101. }
  102.  
  103. char* ShortToString(char* numStr, short val)
  104. {
  105.     return LongToString(numStr, val, true);
  106. }
  107.  
  108. enum
  109. {
  110.     kOTLvlFatal                = 0,
  111.     kOTLvlNonfatal            = 1,
  112.     kOTLvlExtFatal            = 2,
  113.     kOTLvlExtNonfatal        = 3,
  114.     kOTLvlUserErr            = 4,
  115.     kOTLvlInfoErr            = 5,
  116.     kOTLvlInfoOnly            = 6
  117. };
  118. ;
  119.  
  120. char* LevelToString(char* lvlStr, char level)
  121. {
  122.     switch (level)
  123.     {
  124.         case kOTLvlFatal:
  125.             OTStrCopy(lvlStr, "OT Fatal   ");
  126.             break;
  127.             
  128.         case kOTLvlNonfatal:
  129.             OTStrCopy(lvlStr, "OT Nonfatal");
  130.             break;
  131.             
  132.         case kOTLvlExtFatal:
  133.             OTStrCopy(lvlStr, "Ext Fatal  ");
  134.             break;
  135.             
  136.         case kOTLvlExtNonfatal:
  137.             OTStrCopy(lvlStr, "Ext Nonfatal");
  138.             break;
  139.             
  140.         case kOTLvlUserErr:
  141.             OTStrCopy(lvlStr, "User        ");
  142.             break;
  143.             
  144.         case kOTLvlInfoErr:
  145.             OTStrCopy(lvlStr, "Error       ");
  146.             break;
  147.         
  148.         case kOTLvlInfoOnly:
  149.             OTStrCopy(lvlStr, "Info       ");
  150.             break;
  151.  
  152.         default:
  153.             OTStrCopy(lvlStr, "Unknown    ");
  154.             break;
  155.     }
  156.     return lvlStr;
  157. }
  158.             
  159. char* FlagToString(char* flgStr, char flag)
  160. {
  161.     flgStr[0] = '\0';
  162.  
  163.     if (flag & SL_TRACE)
  164.         OTStrCat(flgStr, "Trace ");
  165.     if (flag & SL_ERROR)
  166.         OTStrCat(flgStr, "Error ");
  167.     if (flag & SL_CONSOLE)
  168.         OTStrCat(flgStr, "Console ");
  169.     
  170.     if (flag & SL_FATAL)
  171.         OTStrCat(flgStr, "Fatal ");
  172.     if (flag & SL_NOTIFY)
  173.         OTStrCat(flgStr, "Notify ");
  174.     if (flag & SL_WARN)
  175.         OTStrCat(flgStr, "Warning ");
  176.     if (flag & SL_NOTE)
  177.         OTStrCat(flgStr, "Notice ");
  178.  
  179.     return flgStr;
  180. }
  181.  
  182. StreamLogApp* streamLogApp;
  183.  
  184. typedef OTBuffer* (*MyReadMessage)(OTReadInfo*);
  185.             
  186. pascal void NotifyRoutine(void* fd, OTEventCode code, 
  187.                                            OTResult,void*)
  188. {
  189.     static gBaseMS        = 0;
  190.     char        outStr[1024], tempStr[64];
  191.     OTBuffer*    otbuffer;
  192.     OTReadInfo    readInfo;
  193.     OTBuffer*    mp;
  194.     log_ctl*    entryInfo;
  195.  
  196. //    DebugStr((const unsigned char *)"\pEntered Notify Proc");
  197.     switch (code) {
  198.         case kSIGNALEVENT+SIGPOLL:
  199.             readInfo.fType        = (UInt32)-2;
  200.             readInfo.fCommand    = 0;
  201.             otbuffer = OTReadMessage((StreamRef)fd, &readInfo);
  202.             while ( otbuffer != NULL )
  203.             {
  204.                 if ( (otbuffer->fType == M_PROTO || otbuffer->fType == M_PCPROTO) &&
  205.                      otbuffer->fLen == sizeof(log_ctl) )
  206.                 {
  207.                     entryInfo = (log_ctl*)otbuffer->fData;
  208.                     outStr[0] = '\015';
  209.                     OTStrCat(outStr, "Time: ");
  210.                     strftime(outStr + 1, sizeof(outStr) - 1, "%a, %b %d @ %H:%M:%S.",
  211.                              localtime((const time_t*)&entryInfo->ttime));
  212.                     if ( gBaseMS == 0 )
  213.                     {
  214.                         gBaseMS        = entryInfo->ltime;
  215.                         OTStrCat(outStr, "000");
  216.                     }
  217.                     else
  218.                     {
  219.                         UInt32 val = (entryInfo->ltime - gBaseMS) % 1000;
  220.                         size_t len = OTStrLength(outStr);
  221.                         outStr[len++] = (val / 100) + '0';
  222.                         val = val % 100;
  223.                         outStr[len++] = (val / 10) + '0';
  224.                         outStr[len++] = (val % 10) + '0';
  225.                         outStr[len] = '\0';
  226.                     }
  227.                     OTStrCat(outStr, "\015  Mid: ");
  228.                     OTStrCat(outStr, ShortToString(tempStr, entryInfo->mid));
  229.                     OTStrCat(outStr, " Sid: ");
  230.                     OTStrCat(outStr, ShortToString(tempStr, entryInfo->sid));
  231.                     OTStrCat(outStr, " Flag: ");
  232.                     OTStrCat(outStr, FlagToString(tempStr, entryInfo->flags));
  233.                     OTStrCat(outStr, " Level: ");
  234.                     OTStrCat(outStr, LevelToString(tempStr, entryInfo->level));
  235.                     OTStrCat(outStr, "\015    ");
  236.                     mp = otbuffer->fNext;
  237.                     /* Loop reading trace messages and printing them on stdout. */
  238.                     while ( mp != NULL )
  239.                     {
  240.                         if ( mp->fType == M_DATA )
  241.                         {
  242.                             size_t    toCat;
  243.                             size_t    len = OTStrLength(outStr);
  244.                             
  245.                             if ( mp->fLen + len < sizeof(outStr) - 2 )
  246.                                 toCat = mp->fLen;
  247.                             else
  248.                                 toCat = sizeof(outStr) - len - 2;
  249.                             OTMemcpy(outStr + len, (char*)mp->fData, toCat);
  250.                             len += toCat;
  251.                             //
  252.                             // Put a Carriage return in case user message does not have it
  253.                             //
  254.                             outStr[len] = '\0';
  255.                             if ( len > 1 )
  256.                             {
  257.                                 size_t    ix;
  258.                                 int        which;
  259.                                 if ( entryInfo->flags & SL_ERROR )    // If SL_ERROR the Window 2
  260.                                     which = 1;
  261.                                 else
  262.                                     which = 0;
  263.                                 for ( ix = 0; ix < len; ++ix )
  264.                                     if ( ((streamLogApp->fFillPtr[which] + 1) & kBufferMask) != streamLogApp->fEmptyPtr[which] )
  265.                                     {
  266.                                         streamLogApp->fBuffer[which][streamLogApp->fFillPtr[which]++] = outStr[ix];
  267.                                         streamLogApp->fFillPtr[which] &= kBufferMask;
  268.                                     }
  269.                             }
  270.                             else
  271.                                 DebugStr((unsigned char *)"mp->fData is null");
  272.                         }                        
  273.                         mp = mp->fNext;
  274.                     }
  275.                 }
  276.                 // Release the OTBuffer
  277.                 OTReleaseBuffer(otbuffer);
  278.     
  279.                 // Try for another message
  280.                 otbuffer = OTReadMessage((StreamRef)fd, &readInfo);
  281.             }
  282.             break;
  283.         default:
  284.             DebugStr((unsigned char *)"Unknown code in NotifyRoutine");
  285.             break;
  286.     }
  287. }
  288.  
  289. extern int errno;
  290.  
  291. char parameter[4][4] = {
  292.     "log",
  293.     "all",
  294.     "all",
  295.     "all"
  296. };
  297.  
  298. #define MI_LOG_DEVICE        "/dev/log"
  299. #define O_RDWR                0x02
  300.  
  301. void StreamLogApp::OpenStream(strioctl* stri)
  302. {
  303. //    char    buf[LOGMSGSZ];
  304.     OSStatus err;
  305.  
  306.  
  307.     /* Open a stream to the log device. */
  308.     fLogStream = OTStreamOpen(MI_LOG_DEVICE, O_RDWR, &err);
  309.     if ( err != noErr ) {
  310. //            perror("couldn't open log device");
  311. //        AlertUser(kPrintManagerErrStrings, eCannotOpenStreamDialog);
  312.         ExitToShell();
  313.     }
  314.     
  315.     /* Set STREAM as non-blocking and Asynchronous */
  316.     OTStreamSetNonBlocking(fLogStream);
  317. //    OTStreamSetAsynchronous(gLogStream);
  318.     
  319.     /* Register as the trace logger. */
  320.     
  321.     {
  322.         struct trace_ids tracep;
  323.     
  324.         stri->ic_cmd = I_TRCLOG;
  325.         stri->ic_timout = -1;
  326.         stri->ic_dp = (char *)&tracep;
  327.         stri->ic_len = sizeof(tracep);
  328.     
  329.         /* Default is to get all messages from all modules. */
  330.         tracep.ti_mid = -1;
  331.         tracep.ti_sid = -1;
  332.         tracep.ti_level = (char)-1;
  333.         err = OTStreamIoctl(fLogStream, I_STR, stri);
  334.     }
  335.     
  336.     if ( err != kOTNoError ) {
  337. //        fprintf(stderr, "ERROR: strace already running\n");
  338. //        AlertUser(kPrintManagerErrStrings, eStreamAlreadyRunningDialog);
  339.         ExitToShell();
  340.     }
  341.     /* Register as the error logger. */
  342.     
  343.     {
  344.         struct trace_ids tracep;
  345.     
  346.         stri->ic_cmd = I_ERRLOG;
  347.         stri->ic_timout = -1;
  348.         stri->ic_dp = (char *)&tracep;
  349.         stri->ic_len = sizeof(tracep);
  350.     
  351.         /* Default is to get all messages from all modules. */
  352.         tracep.ti_mid = -1;
  353.         tracep.ti_sid = -1;
  354.         tracep.ti_level = (char)-1;
  355.         err = OTStreamIoctl(fLogStream, I_STR, stri);
  356.     }
  357.     
  358.     if ( err != kOTNoError ) {
  359. //        fprintf(stderr, "ERROR: strace already running\n");
  360. //        AlertUser(kPrintManagerErrStrings, eStreamAlreadyRunningDialog);
  361.         ExitToShell();
  362.     }
  363.     err = OTStreamIoctl(fLogStream, I_SETSIG,
  364.                     (void*)(S_INPUT | S_RDNORM | S_RDBAND | S_HIPRI | S_OUTPUT | S_WRNORM | 
  365.                     S_WRBAND | S_MSG | S_ERROR | S_HANGUP | S_BANDURG));
  366.                     
  367.     if ( err != kOTNoError ) {
  368. //        fprintf(stderr, "ERROR: strace already running\n");
  369. //        AlertUser(kPrintManagerErrStrings, eStreamAlreadyRunningDialog);
  370.         ExitToShell();
  371.     }
  372.  
  373.     err = OTInstallStreamNotifier(fLogStream, NotifyRoutine, (void*)fLogStream); 
  374.     if ( err != noErr ) {
  375. //        AlertUser(kPrintManagerErrStrings, eCantInstallNotifyProcDialog);
  376.         ExitToShell();
  377.     }
  378.     streamLogApp = this;
  379. }
  380.  
  381. // ===========================================================================
  382. //        • StreamLogApp Class
  383. // ===========================================================================
  384.  
  385. // ---------------------------------------------------------------------------
  386. //        • StreamLogApp
  387. // ---------------------------------------------------------------------------
  388. //    Constructor
  389.  
  390. StreamLogApp::StreamLogApp()
  391. {
  392.         // Register classes for objects created from 'PPob' resources
  393.     URegistrar::RegisterClass('wind', (ClassCreatorFunc) LWindow::CreateWindowStream);
  394.     URegistrar::RegisterClass('scrl', (ClassCreatorFunc) LScroller::CreateScrollerStream);
  395.     URegistrar::RegisterClass('Dtxt', (ClassCreatorFunc) CDirtyText::CreateDirtyTextStream);
  396.     URegistrar::RegisterClass('plac', (ClassCreatorFunc) LPlaceHolder::CreatePlaceHolderStream);
  397.     URegistrar::RegisterClass('prto', (ClassCreatorFunc) LPrintout::CreatePrintoutStream);
  398.     URegistrar::RegisterClass('view', (ClassCreatorFunc) LView::CreateViewStream);
  399.     
  400.     fTraceDoc = new CTextDoc(this, nil);
  401.     fErrorDoc = new CTextDoc(this, nil);
  402.     
  403.     fTraceDoc->SetDescriptor((ConstStr255Param)"\pTrace Log");
  404.     fErrorDoc->SetDescriptor((ConstStr255Param)"\pError Log");
  405.  
  406.     struct strioctl stri;
  407.     fFillPtr[0] = fEmptyPtr[0] = fFillPtr[1] = fEmptyPtr[1] = 0;
  408.     fLogStream = (TSTREAM*)0;
  409.     OSStatus err;
  410.     err = InitOpenTransport();
  411.     if ( err == kOTNoError )
  412.         OpenStream(&stri);
  413. }
  414.  
  415.  
  416. // ---------------------------------------------------------------------------
  417. //        • ~StreamLogApp
  418. // ---------------------------------------------------------------------------
  419. //    Destructor
  420.  
  421. StreamLogApp::~StreamLogApp()
  422. {
  423.     if (fLogStream)
  424.         OTStreamClose(fLogStream);
  425.         
  426.     CloseOpenTransport();    // safe to call even if InitLibraryManager failed
  427.  
  428. }
  429.  
  430. void
  431. StreamLogApp::UseIdleTime(
  432.     const EventRecord    &inMacEvent)
  433. {
  434.     char outStr[128];
  435.     
  436.     for (int window = 0; window < 2; window++)
  437.     {
  438.         if (fEmptyPtr[window] != fFillPtr[window])
  439.         {
  440.             int iy = 0;
  441.             while (fEmptyPtr[window] != fFillPtr[window] && iy < sizeof(outStr))
  442.             {
  443.                 outStr[iy++] = fBuffer[window][fEmptyPtr[window]++];
  444.                 fEmptyPtr[window] &= kBufferMask;
  445.             }
  446.             outStr[iy] = '\0';
  447.             if (window == 0)
  448.                 fTraceDoc->OutString(outStr,iy);
  449.             else
  450.                 fErrorDoc->OutString(outStr, iy);
  451.         }
  452.     }
  453.  
  454.     LDocApplication::UseIdleTime(inMacEvent);
  455. }
  456.  
  457.  
  458. // ---------------------------------------------------------------------------
  459. //        • ObeyCommand
  460. // ---------------------------------------------------------------------------
  461. //    Respond to commands
  462.  
  463. Boolean
  464. StreamLogApp::ObeyCommand(
  465.     CommandT    inCommand,
  466.     void        *ioParam)
  467. {
  468.     Boolean    cmdHandled = true;
  469.     
  470.     switch (inCommand) {
  471.     
  472.         // +++ Add cases here for the commands you handle
  473.         //        Remember to add same cases to FindCommandStatus below
  474.         //        to enable/disable the menu items for the commands
  475.     
  476.         default:
  477.             cmdHandled = LDocApplication::ObeyCommand(inCommand, ioParam);
  478.             break;
  479.     }
  480.     
  481.     return cmdHandled;
  482. }
  483.  
  484.  
  485. // ---------------------------------------------------------------------------
  486. //        • FindCommandStatus
  487. // ---------------------------------------------------------------------------
  488. //    Pass back status of a (menu) command
  489.  
  490. void
  491. StreamLogApp::FindCommandStatus(
  492.     CommandT    inCommand,
  493.     Boolean        &outEnabled,
  494.     Boolean        &outUsesMark,
  495.     Char16        &outMark,
  496.     Str255        outName)
  497. {
  498.     outUsesMark = false;
  499.     
  500.     switch (inCommand) {
  501.     
  502.         case cmd_New:
  503.         case cmd_Open:
  504.         case cmd_Close:
  505.             outEnabled = false;        // Query has reached the top of a command
  506.             outUsesMark = false;    //   chain without any object dealing with
  507.             break;
  508.     
  509.         default:
  510.             LDocApplication::FindCommandStatus(inCommand, outEnabled, outUsesMark,
  511.                                 outMark, outName);
  512.             break;
  513.     }
  514. }
  515.  
  516.  
  517. // ---------------------------------------------------------------------------
  518. //        • OpenDocument
  519. // ---------------------------------------------------------------------------
  520. //    Open a Document file
  521.  
  522. void
  523. StreamLogApp::OpenDocument(
  524.     FSSpec    *inMacFSSpec)
  525. {
  526.     CTextDoc    *theDoc = new CTextDoc(this, inMacFSSpec);
  527. }
  528.  
  529.  
  530. // ---------------------------------------------------------------------------
  531. //        • MakeNewDocument
  532. // ---------------------------------------------------------------------------
  533. //    Create a new Document
  534.  
  535. LModelObject*
  536. StreamLogApp::MakeNewDocument()
  537. {
  538.     CTextDoc    *theDoc = new CTextDoc(this, nil);
  539.     return theDoc;
  540. }
  541.  
  542.  
  543. // ---------------------------------------------------------------------------
  544. //        • ChooseDocument
  545. // ---------------------------------------------------------------------------
  546. //    Prompt the user to select a document to open
  547.  
  548. void
  549. StreamLogApp::ChooseDocument()
  550. {
  551.     StandardFileReply    macFileReply;
  552.     SFTypeList            typeList;
  553.     
  554.     UDesktop::Deactivate();
  555.     typeList[0] = 'TEXT';
  556.     ::StandardGetFile(nil, 1, typeList, &macFileReply);
  557.     UDesktop::Activate();
  558.     if (macFileReply.sfGood) {
  559.         OpenDocument(&macFileReply.sfFile);
  560.     }
  561. }
  562.